/****************************************************************************************
 * 
 *  Author:         CFY
 *  Date:           2025-07-10
 *  Description:    共享内存工具类
 *  Version:        V1.2
 * 
****************************************************************************************/

#include "shmem.h"

/**
 * @brief   初始化共享内存
 * @param   param       用来存储共享内存的相关信息
 * @param   name        共享内存标识名
 * @param   size        共享内存的大小
 * @return  成功返回    0
 *          失败返回    -1        
 */
int shmem_init(struct shmem_param *param, const char *name, size_t size)
{
    char path[256];

    if(NULL == name)
    {
        printf("shmem_init(), name can not be empty!\n");
        return -1;
    }

    sprintf(path, "%s%s", SHMEM_PATH, name);  

    if (0 != access(path, F_OK))        // 如果文件不存在才创建
    {
        char sys_cmd[256];
        sprintf(sys_cmd, "%s %s", "touch", path);   
        if(0 != system(sys_cmd))
        {
            ERROR("system");
            return -1;
        }
    }

    // 1. 创建唯一key值
    int key = ftok(path, 's');
    if(-1 == key)
    {
        ERROR("ftok");
        return -1;
    }

    // 2. 创建或打开共享内存
    int shmem_id = shmget(key, size, IPC_CREAT|0666);
    if(-1 == shmem_id)
    {
        ERROR("shmget");
        return -1;
    }

    // 3. 映射共享内存
    void *addr = shmat(shmem_id, NULL, 0);
    if((void *)-1 == addr)
    {
        ERROR("shmat");
        return -1;
    }

    // 将初始化的共享内存保存到结构体中 
    param->key = key;
    param->id = shmem_id;
    param->size = size;
    param->addr = addr;

    printf("shmem_init success. id : [%d]\n", shmem_id);
    return 0;
}


/**
 * @brief   删除共享内存
 * @param   param       用来存储共享内存的相关信息
 * @return  成功返回    0
 *          失败返回    -1        
 */
int shmem_del(struct shmem_param *param)
{
    if(NULL == param)
    {
        printf("shmem_del(), param can not be empty!\n");
        return -1;
    }

    // 4. 取消映射
    if(-1 == shmdt(param->addr))
    {
        ERROR("shmdt");
        return -1;
    }

    // 5. 删除共享内存
    if(-1 == shmctl(param->id, IPC_RMID, NULL))
    {
        ERROR("shmat");
        return -1;
    }

    return 0;
}

/**
 * @brief   写入共享内存
 * @param   param       用来存储共享内存的相关信息
 * @param   data        要写入共享内存的数据
 * @param   size        要写入共享内存的数据大小
 * @return  成功返回    0
 *          失败返回    -1        
 */
int shmem_write(struct shmem_param *param, void *data, size_t size)
{
    if(size > param->size)
    {
        printf("The data to be written is too large.\n");
        return -1;
    }
    if(NULL == data)
    {
        printf("The data to be written is empty.\n");
        return -1;
    }

    memcpy(param->addr, data, size);
    printf("write success.\n");
    return 0;
}